﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;

namespace ConsolidationTool.Common
{

    class CacheMergeSPItem : CacheSPItem
    {

        public CacheMergeSPItem(SPListItem item)
            : base(item)
        {
        }

        public void MergeExchangeRate(ExchangeRate er)
        {
            if (!isKoItem)
            {
                Fields.ToList().ForEach(p =>
                {
                    if (p.Key.StartsWith("CM_") || p.Key.StartsWith("YTDM1_"))
                    {
                        //process to fix each field exchange rate cost 
                    }

                });
            }
        }
    }
    public class CacheSPItem
    {
        public CacheSPItem() {
            KoFields = new List<koOutputEntity>();
            Fields = new Dictionary<string, string>();
        }
        public CacheSPItem(int year,int month,string list)
        {
            this.Year = year;
            this.Month = month;
            this.List = list;
        }
        public CacheSPItem(SPListItem item)
        {
            if (item == null) { return; }

            DateTime now = DateTime.Now;
            Identity = Utilities.CreateItemIndentity(item.ParentList.Title, item["CoCd"] + "", item["Year"] + "", item["Month"] + "");
            CoCd = item["CoCd"] + "";
            CoName = item["CoName"] + "";

            int.TryParse(item["Year"] + "", out Year);
            int.TryParse(item["Month"] + "", out Month);

            Currency = item["Currency"] + "";
            LocalCurrency = Currency.StartsWith("K") ? Currency.Substring(1) : Currency;

            isKoItem = item.ContentType.Name == "BudgetBillBase";
            List = item.ParentList.Title;

            if (isKoItem)
            {
                KoFields = BusinessService.RefJsonData<koOutputEntity>(item["BillData"] + "");
                var subrows = KoFields.Where(p => p.subrow != null);
                subrows.ToList().ForEach(p =>
                {
                    p.subrow.ForEach(a =>
                    {
                        var pros = a.GetType().GetProperties().Select(cp => cp.Name);
                        var newKo = new koOutputEntity();

                        pros.ToList().ForEach(d =>
                        {
                            newKo.TrySetValue(d, a.TryGetValue(d));
                        });
                        newKo.issubrow = true;
                        KoFields.Add(newKo);
                    });
                    //  KoFields.AddRange(p.subrow.Cast<BaseKoOutputEntity>().Cast<koOutputEntity>());
                });
            }
            else
                Fields = CreateItemFieldsCache(item);

            // Utilities.Log(string.Format("[Brochure Report] Create Cache :{0} need:{1}", Identity, DateTime.Now - now));
        }
         

        private Dictionary<string, string> CreateItemFieldsCache(SPListItem item)
        {
            var cc = new Dictionary<string, string>();
            try
            {
                int fieldCount = item.ContentType.Fields.Count;
                for (int i = 0; i < fieldCount; i++)
                {
                    var field = item.ContentType.Fields[i];
                    string fixedName = field.StaticName.Replace("_x002d_", "-");
                    if (cc.ContainsKey(fixedName)) continue;

                    cc.Add(fixedName, item[field.StaticName] + "");
                }
                return cc;
            }
            catch (Exception ex)
            {
                Utilities.Log(string.Format("[Exception]-{0} ", ex.Message));
            }
            return cc;
        }


        public string Identity { get; set; }
        public string List { get; set; }
        private List<CacheSPItem> _YTDItems;
        /// <summary>
        /// the all items from current year to current day
        /// </summary>
        public List<CacheSPItem> YTDItems
        {
            get
            {
                if (_YTDItems == null)
                    _YTDItems = GetHistoryItem(true, true);

                return _YTDItems;
            }
        }
        private List<CacheSPItem> _Last12MonthItem;
        /// <summary>
        /// the roll back 12 months items
        /// </summary>
        public List<CacheSPItem> Last12MonthItem
        {
            get
            {
                if (_Last12MonthItem == null)
                    _Last12MonthItem = GetHistoryItem(false, false);

                return _Last12MonthItem;
            }
        } 
        public bool isKoItem { get; set; }
        public bool isConlidation { get { return List.StartsWith("R_"); } }
        public Dictionary<string, string> Fields { get; set; }
        public List<koOutputEntity> KoFields { get; set; }
        public string CoName { get; set; }
        public string CoCd { get; set; }
        public string Currency { get; set; } 
        public string LocalCurrency { get; set; }
        public List<ExchangeRate> ExchangeRate { get; set; }
        public int Year, Month;


        public string this[string fieldName]
        {
            get
            {
                return this.GetValue(fieldName);
            }
        }

        private string GetValue(string fieldName)
        {
            try
            {
                if (!isKoItem)
                {
                    if (Fields == null) return "0";
                    if (Fields.ContainsKey(fieldName))
                        return Fields[fieldName];
                    if (Fields.ContainsKey(fieldName.Replace('-', '_')))
                        return Fields[fieldName.Replace('-', '_')];
                    else
                        return Fields[fieldName.Substring(fieldName.IndexOf('_') + 1)];
                }
                //如果是ko方式的数据，那么传入字段应有对应列名，如NF01020100|Jan
                if (KoFields == null) return "0";
                string row = string.Empty;
                string field = string.Empty;

                if (fieldName.IndexOf("|") != -1)
                {
                    row = fieldName.Split('|')[0];
                    field = fieldName.Split('|')[1];
                }
                else if (fieldName.IndexOf("_") != -1)
                {
                    int lastIndex = fieldName.LastIndexOf('_');
                    row = fieldName.Split('_').Last();
                    field = fieldName.Substring(0, lastIndex);
                }
                else if (fieldName.IndexOf("&") != -1)
                { 
                    row = fieldName.Split('&').First();
                    field = fieldName.Split('&').Last();
                }

                var oeo = KoFields.FirstOrDefault(p => p.accountcode == row);
                if (oeo != null)
                    return oeo.TryGetValue(field) + "";

                Utilities.Log("[Unkown Field]: " + fieldName + " List:" + List);

            }
            catch (Exception ex)
            {
                Utilities.Log("[Exception] - " + fieldName + "-" + ex.Message);
            }
            return "0";
        }

        public decimal GetYTDValue(ARTReportFromItem from, SearchEntity se)
        {
            decimal value = 0.00M;
            string field = "";

            if (from.budget)
            {
                if (KoFields == null) return value;

                return KoFields.GetBudgetYTDValue(from, se.Month);
            }
            else if (from.komode )
            {
                if (KoFields != null)
                    return KoFields.GetFieldValue(from.identity, from.field);
                field = from.identity + "&CM";
            }
            else
                field = from.identity.StartsWith(from.field) ? from.identity : from.field + from.identity;

            //we hope the get pass 12 month value and get ytd value all transfer to this way TODO
            if (from.isConsolidationWay)
            {
                decimal rollingYTDValue = 0.00M;
                YTDItems.ForEach(v =>
                {
                    rollingYTDValue += BusinessService.decimalParse(v[field]);
                });

                return rollingYTDValue;
            }

            value = BusinessService.GetLast12MonthFieldValue(se.Entity, se.Year, se.Month, from.list, new string[] { field }, "", false, true);

            return value;
        }

        public List<CacheSPItem> GetHistoryItem(bool withCurrentMonth, bool YTD)
        {
            var temp = new List<CacheSPItem>();

            int y = Year;
            int y_1 = y - 1;
            int y_2 = y + 1;

            int m = Month;
            int l_m = m + 1;

            if (withCurrentMonth)
                l_m = m;

            SPWeb web = SPContext.Current.Web;
            SPList list = web.Lists.TryGetList(List);
            if (list == null) return temp;
            SPQuery spQuery = new SPQuery();
            spQuery.Query = string.Format(@"<Where>
                                              <And>
                                                 <Geq>
                                                    <FieldRef Name='Year' />
                                                    <Value Type='Integer'>{0}</Value>
                                                 </Geq>
                                                 <And>
                                                    <Leq>
                                                       <FieldRef Name='Year' />
                                                       <Value Type='Integer'>{1}</Value>
                                                    </Leq>
                                                    <Eq>
                                                       <FieldRef Name='CoCd' />
                                                       <Value Type='Text'>{2}</Value>
                                                    </Eq>
                                                 </And>
                                              </And>
                                           </Where>", y_1, y_2, CoCd);
            if (isConlidation) { 
                spQuery.Query = string.Format(@"<Where>
                                                 <Geq>
                                                    <FieldRef Name='Year' />
                                                    <Value Type='Integer'>{0}</Value>
                                                 </Geq>
                                                <Leq>
                                                    <FieldRef Name='Year' />
                                                    <Value Type='Integer'>{1}</Value>
                                                </Leq>
                                              </And>
                                           </Where>", y_1, y_2);
            }
            SPListItemCollection items = list.GetItems(spQuery);
            if (items.Count > 0)
            {
                int itemCount = items.Count;
                for (int i = 0; i < itemCount; i++)
                {
                    var item = items[i];
                    int itemYear = int.Parse(item["Year"] + "");
                    int itemMonth = int.Parse(item["Month"] + "");

                    if (YTD && (itemYear == Year && itemMonth <= Month))
                    {
                        temp.Add(new CacheSPItem(item));
                    }
                    else if (!YTD && ((itemYear == y_1 && itemMonth >= l_m) ||
                        (itemYear == y && itemMonth <= m)))
                    {
                        temp.Add(new CacheSPItem(item));
                    }
                }
            }


            return temp;

        }

        public decimal GetL12Value(ARTReportFromItem from, SearchEntity se)
        {
            decimal value = 0.00M;

            if (from.budget)
            {
                if (KoFields == null) return value;
                //var oeo = KoFields.FirstOrDefault(p => p.accountcode == from.identity);
                //if (oeo == null) return value;
                //for (int i = 1; i <= 12; i++)
                //{
                //    value += BusinessService.GetObjectValue(oeo, from.profix + BusinessService.GetEngMonth(i) + from.suffix);
                //}
                return KoFields.GetBudgetYTDValue(from, 12);
                // return value;
            }


            string field = "";
            if (from.komode)
            {
                field = from.identity + "&CM";
            }
            else
                field = from.identity.StartsWith(from.field) ? from.identity : from.field + from.identity;

            //we hope the get pass 12 month value and get ytd value all transfer to this way TODO
            if (from.isConsolidationWay) {
                decimal rolling12MonthValue = 0.00M;
                Last12MonthItem.ForEach(l12 =>
                {
                    rolling12MonthValue += BusinessService.decimalParse(l12[field]);
                });

                return rolling12MonthValue;
            }

            value = BusinessService.GetLast12MonthFieldValue(se.Entity, se.Year, se.Month, from.list, new string[] { field }, "", false, false);

            return value;

        }

        public string GetMYTDValue(ARTReportFromItem from, SearchEntity se)
        {
            var newse = se.Clone() as SearchEntity;
            newse.fields = from.identity.Split('&');
            newse.equ = from.equ;
            return BusinessService.GetBudgetYTDValue(newse, KoFields).ToString("N2");
        }

         
        public decimal GetAfterRateValue(ActualMergeRow p, string fieldtype, string forceRateType)
        {
            decimal temp = 0.00M;

            return GetAfterRateValue(p, fieldtype, forceRateType, out temp);
        }
        public decimal GetAfterRateValue(ActualMergeRow p, string fieldtype, string forceRateType, out decimal OriginalValue)
        {
            decimal value = 0.00M; OriginalValue = 0.00M;
            forceRateType = forceRateType.IsNullOrEmpty() ? fieldtype : forceRateType;
 
                if (fieldtype == "YTD")
                {
                    //var cm = BusinessService.decimalParse(GetValue("CM_" + accountcode));
                    //var ytdm1 = BusinessService.decimalParse(GetValue("YTDM1_" + accountcode));

                    YTDItems.ForEach(c =>
                    {
                        string receiveField = "CM_" + p.accountcode;
                        receiveField = p.forcefield.IsNullOrEmpty() ? receiveField : p.forcefield;

                        value += BusinessService.decimalParse(c[receiveField]);
                    });
                }
                else
                {
                    string receiveField = fieldtype + "_" + p.accountcode;
                    receiveField = p.forcefield.IsNullOrEmpty() ? receiveField : p.forcefield;

                    value = BusinessService.decimalParse(GetValue(receiveField));
                }
          
            if (p.convertT.IndexOf(CoName) != -1)
                value = value / 1000;

            OriginalValue = value;
            if (p.exchangerate)
            {
                value = Utilities.Division(value, BusinessService.decimalParse(ExchangeRate.First().TryGetValue(forceRateType) + ""));
            }

            return value;
        }


    }

}
